package com.littlerpc.provider;


import com.littlerpc.protocol.codec.Serializer;
import com.littlerpc.protocol.net.annotation.RpcService;
import com.littlerpc.protocol.net.common.*;
import com.littlerpc.registry.zookeeper.ZookeeperConfig;
import com.littlerpc.registry.zookeeper.ZookeeperRegistry;
import lombok.Setter;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.InetAddress;
import java.util.Map;

/**
 *
 * @author ChengPeng
 * @date 2017/6/16
 */

public class SpringServiceProvide implements ApplicationContextAware, InitializingBean, DisposableBean {

    private RpcServer server;


    @Setter
    /**
     * zk相关信息
     */
    public ZookeeperConfig zkConf;
    @Setter
    /**
     * 是用那种aio框架
     */
    private String protocol;
    @Setter

    /**
     * 使用那种序列化
     */
    private String serialize;
    @Setter
    /**
     * 端口
     */
    private int port;


    @Override
    public void destroy() throws Exception {
        server.stop();
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        //启动server
        new Thread(() ->server.start()).start();

        if(zkConf != null) {
            ZookeeperRegistry zookeeperRegistry = new ZookeeperRegistry(zkConf);
            if(zookeeperRegistry.isConnected()){
                String nodeData = InetAddress.getLocalHost().getHostAddress()+":"+port;
                System.out.println("向zk注册：" + nodeData);
                zookeeperRegistry.register(nodeData);
            }
        }


    }

    @Override
    /**
     * 在spring初始化的时候，获取所有的rpcservice注解，并将对象保存到父类的对象池中
     */
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {

        //初始化server
        createRpcServer();

        //获取实现类对应的接口
        Map<String, Object> beans = applicationContext.getBeansWithAnnotation(RpcService.class);

        beans.forEach((k,bean) -> {
            String name = bean.getClass().getAnnotation(RpcService.class).value().getName();
            ServiceBeanResource.putService(name,bean);
        });

    }

    private void createRpcServer() {

        Serializer serializer = SerializerEnum.match(serialize);
        Class<? extends RpcServer> rpcServer = NetProtocolEmum.getRpcServer(protocol);
        try {
            Constructor<? extends RpcServer> constructor = rpcServer.getConstructor(int.class, Serializer.class);
            server = constructor.newInstance(port,serializer);
            System.out.println("*********************************" + server);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException | InstantiationException |InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}
